
package com.scs.application.modules.base.controller;


import cn.afterturn.easypoi.excel.entity.ExportParams;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.scs.application.core.exceptions.BusinessException;
import com.scs.application.core.exceptions.ExportException;
import com.scs.application.core.exceptions.ImportException;
import com.scs.application.core.model.CommonResult;
import com.scs.application.core.model.ImportResult;
import com.scs.application.core.model.PageResult;
import com.scs.application.core.model.RestResult;
import com.scs.application.core.mvc.controller.CrudController;
import com.scs.application.core.mvc.controller.ImAndExAbleController;
import com.scs.application.core.threadLock.ThreadLock;
import com.scs.application.core.utils.BeanUtils;
import com.scs.application.core.utils.DateUtils;
import com.scs.application.core.utils.PoiUtils;
import com.scs.application.core.utils.UserUtils;
import com.scs.application.modules.base.dto.AutoCorrectionCatalogDTO;
import com.scs.application.modules.base.dto.DisabledParamDTO;
import com.scs.application.modules.base.dto.ExcelMaterialDTO;
import com.scs.application.modules.base.entity.*;
import com.scs.application.modules.base.enums.ExcelImportBaseDataConfig;
import com.scs.application.modules.base.mapper.MaterialMapper;
import com.scs.application.modules.base.request.MaterialQueryRequest;
import com.scs.application.modules.base.service.*;
import com.scs.application.modules.base.vo.ExcelMaterialVO;
import com.scs.application.modules.base.vo.MaterialVO;
import com.scs.application.modules.design.service.QueryGenerator;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.io.Serializable;
import java.util.List;
import java.util.Map;

/**
 * 商品 controller
 */
@AllArgsConstructor
@RestController
@SuppressWarnings("all")
@RequestMapping("/base/materials")
public class MaterialController extends CrudController<Material, String, MaterialService> implements ImAndExAbleController<MaterialQueryRequest> {

    private final MaterialSpecService materialSpecService;
    private final MaterialMapper materialMapper;
    private final MaterialCatalogService materialCatalogService;
    private final SupplierService supplierService;
    private final ManufacturerService manufacturerService;

    @PostMapping
    public CommonResult add(@RequestBody @Valid Material entity) {
        entity.setSupplierId(UserUtils.getSupplierId());
        boolean bSave = service.saveCascadeById(entity);
        return bSave ? CommonResult.ok("新增成功", entity) : CommonResult.error("新增失败");
    }

    @Override
    @PutMapping
    public CommonResult update(@RequestBody @Valid Material entity) {
        entity.setSupplierId(UserUtils.getSupplierId());
        boolean bUpdate = service.updateCascadeById(entity);
        return bUpdate ? CommonResult.ok("保存成功", entity) : CommonResult.error("保存失败");
    }

    @GetMapping("/page")
    public PageResult page(MaterialQueryRequest request) {
        IPage<MaterialVO> page = service.page(request);
        return PageResult.ok("查询成功", page.getRecords(), page.getTotal());
    }

    @GetMapping("/list")
    public CommonResult list(MaterialQueryRequest request) {
        List<MaterialVO> list = service.list(request);
        return CommonResult.ok("查询成功", list);
    }


    /**
     * 商品管理 导出数据
     */
    @Override
    public void excelExport(MaterialQueryRequest request) {
        String fileName = "耗材信息" + DateUtils.format(DateUtils.now(), "yyyyMMddHHmmss") + ".xlsx";

        ExportParams params = PoiUtils.getDefaultExportParams("耗材导出信息", "耗材信息", true);

        request.setSupplierId(UserUtils.isSupplier() ? UserUtils.getSupplierId() : null);
        List<ExcelMaterialVO> list = service.listExcel(request);
        List<ExcelMaterialDTO> dtos = Lists.newArrayListWithCapacity(list.size());
        BeanUtils.copyProperties(list, dtos, ExcelMaterialDTO.class);

        try {
            setDownloadParam(fileName);
            PoiUtils.exportExcel(response().getOutputStream(), params, ExcelMaterialDTO.class, dtos);
        } catch (IOException e) {
            throw new ExportException("导出异常", e);
        }
    }

    /**
     * 商品管理 导出数据模板
     */
    @Override
    public void excelTemplate(MaterialQueryRequest request) {
        String fileName = "4商品导入.xlsx";
        ExportParams params = PoiUtils.getDefaultExportParams("耗材导入模板", "耗材信息", true);
        params.setExclusions(new String[]{"错误行号", "错误信息", "品类名称", "助记码"});
        if (UserUtils.isSupplier()) {
            params.setExclusions(new String[]{"错误行号", "错误信息", "品类名称", "助记码", "供应商名称"});
        }
        ExcelMaterialDTO mockData = PoiUtils.mockData(ExcelMaterialDTO.class);
        try {
            setDownloadParam(fileName);
            PoiUtils.exportExcel(response().getOutputStream(), params, ExcelMaterialDTO.class, Lists.newArrayList(mockData));
        } catch (IOException e) {
            throw new ExportException("导出异常", e);
        }
    }

    /**
     * 商品管理 导入数据
     */
    @Override
    public CommonResult<ImportResult> excelImport(MultipartFile file) throws ImportException {
        return CommonResult.ok("导入成功", service.excelImport(file));
    }

    /**
     * 自动修正商品分类
     */
    @PostMapping("/auto_correction_catalog")
    public CommonResult autoCorrectionCatalog(@RequestBody AutoCorrectionCatalogDTO dto) {
        this.service.autoCorrectionCatalog(dto);
        return CommonResult.ok("所有分类已修正完成");
    }



    /***
     * @param request
     * @Description:  通用分页
     */
    @GetMapping("/pageCommon")
    @Override
    public PageResult pageCommon(HttpServletRequest request, Material entity) {
        IPage<MaterialVO> page = QueryGenerator.parsePage(request);
        QueryWrapper<MaterialVO> queryWrapper = QueryGenerator.initQueryWrapper(request);
        fillQueryAuth(queryWrapper,entity);
        IPage pageResult = materialMapper.pageCommon(page, queryWrapper);
        return PageResult.ok("查询成功", pageResult.getRecords(), pageResult.getTotal());
    }

    private void fillEntity(Material entity) {
        MaterialCatalog materialCatalog =  materialCatalogService.getById(entity.getCatalogId());
        if (materialCatalog != null) {
            entity.setCatalogName(materialCatalog.getName());
        }
        Supplier supplier =  supplierService.getById(entity.getSupplierId());
        if (supplier != null) {
            entity.setSupplierName(supplier.getName());
        }
        Manufacturer manufacturer =  manufacturerService.getById(entity.getManufacturerId());
        if (manufacturer != null) {
            entity.setManufacturerName(manufacturer.getName());
        }

        List<MaterialSpec> materialSpecList = materialSpecService.list(Wrappers.<MaterialSpec>query().eq("material_id",entity.getId()));
        BusinessException.throwErrorIf(materialSpecList != null && materialSpecList.size() > 1, "该商品出现多个规格，请联系运维人员");
        if (materialSpecList != null && materialSpecList.size() == 1) {
            entity.setMaterialSpec(materialSpecList.get(0));
        } else{
            MaterialSpec materialSpec = new MaterialSpec();
            materialSpec.setMaterialId(entity.getId());
            entity.setMaterialSpec(materialSpec);
        }

    }


    /***
     * @param entity
     * @Description:  通用保存、更新
     */
    @PostMapping("/saveOrUpdateCommon")
    public RestResult saveOrUpdateCommon(@Valid @RequestBody Material entity) {
        boolean isOk = service.saveOrUpdate(entity);
        if (!isOk) {
            return RestResult.error("数据保存失败");
        }

        this.fillEntity(entity);
        return RestResult.ok("数据保存成功", entity);
    }

    /***
     * @param id
     * @Description:  通用查找，单个
     */
    @GetMapping("/findByIdCommon")
    public RestResult findByIdCommon(@RequestParam("id") Serializable id) {
        Material entity = service.getById(id);
        if (entity == null) {
            return RestResult.error("数据查询失败<br>可能所操作数据已被删除，请刷新后重新尝试操作");
        }
        this.fillEntity(entity);
        return RestResult.ok("获取数据成功", entity);
    }

    /***
     * @Description:  通用删除，多个
     */
    @DeleteMapping("/deleteBatchCommon")
    public RestResult deleteBatchCommon(@RequestBody Map<String, Object> para) {
        List<Serializable> ids = (List<Serializable>) para.get("ids");
        Boolean isOk = service.removeCascadeBatchByIds(ids);
        if (!isOk) {
            return RestResult.error("数据删除失败<br>可能所操作数据已被删除，请刷新页面重新尝试操作");
        }
        return RestResult.ok("数据删除成功");
    }

    /***
     * @Description:  批量禁用
     */
    @PostMapping("/disabledBatch")
    public RestResult disabledBatch(@Valid @RequestBody DisabledParamDTO disabledParam) {
        return RestResult.ok(service.disabledBatch(disabledParam, true));
    }

    /***
     * @Description:  批量启用
     */
    @PostMapping("/enabledBatch")
    public RestResult enabledBatch(@Valid @RequestBody DisabledParamDTO disabledParam) {
        return RestResult.ok(service.disabledBatch(disabledParam,false));
    }



    /**
     * @description: 导入商品 下载导入模板
     **/
    @GetMapping("/excelDownloadTempForDataImport")
    public void excelDownloadTempForDataImport(HttpServletResponse response, @RequestParam Map<String, String> reqData) {
        service.excelDownloadTemp(response,reqData, ExcelImportBaseDataConfig.getMatrDataImport());
    }

    /**
     * @description: 导入商品 导入数据
     **/
    @RequestMapping(value = "/excelImportForDataImport", method = RequestMethod.POST)
    @ThreadLock(busType = "导入商品")
    public RestResult excelImportForDataImport(@RequestParam(value = "file") MultipartFile file, @RequestParam Map<String, String> reqData) {
        try {
            return  service.excelImportForDataImport(file,reqData);
        }catch (Exception e) {
            logger.error("excelImportForDataImport.error",e);
            return  RestResult.error(e.getMessage());
        }
    }
}
